//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#ifndef __ELASTOS_GRAFIX_FUSION__VECTOR_H__
#define __ELASTOS_GRAFIX_FUSION__VECTOR_H__

#include <elatypes.h>
#include <grafixcomm.h>

typedef struct tagFusionVector {
    Void     ** elements;
    Int32         count;
    Int32         capacity;
    Int32         order;
} FusionVector;

Void FusionVectorInit(
            FusionVector          * vector,
            Int32                     capacity);

Void FusionVectorDestroy(
            FusionVector          * vector);

ECode FusionVectorAdd(
            FusionVector          * vector,
            Void                  * element);

ECode FusionVectorInsert(
            FusionVector          * vector,
            Void                  * element,
            Int32                     index);

ECode FusionVectorMove(
            FusionVector          * vector,
            Int32                     from,
            Int32                     to);

Void  FusionVectorRemove(
            FusionVector          * vector,
            Int32                     index);

ECode FusionVectorRemoveLast(
            FusionVector          * vector);

INLINE Boolean
FusionVectorHasElements(
    const FusionVector * vector)
{
    return vector->count > 0;
}

INLINE Boolean
FusionVectorIsEmpty(
    const FusionVector * vector)
{
    return vector->count == 0;
}

INLINE Int32
FusionVectorSize(
    const FusionVector * vector)
{
    return vector->count;
}

INLINE Void *
FusionVectorAt(
    const FusionVector * vector,
    Int32 index)
{
    return vector->elements[index];
}

INLINE Boolean
FusionVectorContains(
    const FusionVector * vector,
    const Void * element)
{
    int             i;
    int             count;
    Void * const  * elements;

    count = vector->count;
    elements = vector->elements;

    // Start with more recently added elements.
    //
    for (i = count - 1; i >= 0; i--)
        if (elements[i] == element)
            return TRUE;

    return FALSE;
}

INLINE Int32
FusionVectorIndexOf(
    const FusionVector * vector,
    const Void * element)
{
    Int32             i;
    Int32             count;
    Void * const  * elements;

    count       = vector->count;
    elements    = vector->elements;

    // Start with more recently added elements.
    //
    for (i = count - 1; i >= 0; i--)
        if (elements[i] == element)
            return i;

    // In case the return value isn't checked
    // this will most likely generate a bad address.
    //
    return -1;
}

#define fusion_vector_foreach(element, index, vector)                       \
    for ((index) = 0;                                                       \
        (index) < (vector).count && (element = (vector).elements[index]);   \
        (index)++)

#define fusion_vector_foreach_reverse(element, index, vector)               \
    for (index = (vector).count - 1;                                        \
        index >= 0 && (element = (vector).elements[index]);                 \
        index--)

#endif  // __ELASTOS_GRAFIX_FUSION__VECTOR_H__
